#ifndef LOGGER_H_
#define LOGGER_H_

#include <string>
#include <fstream>
#include <thread>
#include <atomic>
#include "../lfqueue/iqueue.h"

// It's not very good idea to use Logger directly. Please, use special defines  
// for conditional compilation

class Logger {
	public :

	enum Priority {
		DEBUG,
		CONFIG,
		INFO,
		WARNING,
		ERROR
	};
	
	static void Start(Priority min_priority, const std::string& log_file);
	static void Stop();

	static void Write(Priority priority, const std::string &message);

	private :

	static void LoggerThreadFunc();
	
	Logger();
	Logger(const Logger&) = delete;
	Logger& operator=(const Logger&) = delete;

	~Logger();

	std::atomic<bool> active_;
	std::ofstream fout_;
	Priority min_priority_;

	IQueue<std::string> *message_queue_ = nullptr;
	
	std::thread *pthread_ = nullptr;

	static Logger instance_;
	
};

#ifndef LOG_STAMP
#define LOG_STAMP std::string(__FILE__) + ':' + std::to_string(__LINE__) + \
    ':' + __func__ + ": "
#endif

#ifdef ENABLE_LOGGER
 
#define LOGGER_START(MIN_PRIORITY, FILE) Logger::Start(MIN_PRIORITY, FILE)
#define LOGGER_STOP() Logger::Stop()
#define LOGGER_WRITEQ(PRIORITY, MESSAGE) Logger::Write(PRIORITY, MESSAGE)
#define LOGGER_WRITE(PRIORITY, MESSAGE) Logger::Write(PRIORITY, LOG_STAMP + MESSAGE)
 
#else
 
#define LOGGER_START(MIN_PRIORITY, FILE)
#define LOGGER_STOP()
#define LOGGER_WRITE(PRIORITY, MESSAGE)
#define LOGGER_WRITEQ(PRIORITY, MESSAGE)
 
#endif

#endif //LOGGER_H_

